package _9_博客园Redis

import (
	"fmt"
	"github.com/go-redis/redis"
)

/*Redis列表是简单的字符串列表，列表是有序的，列表中的元素可以重复。
可以添加一个元素到列表的头部（左边）或者尾部（右边）
golang redis list数据操作常用函数：
	LPush - 从列表左边插入数据
	LPushX - 跟LPush的区别是，仅当列表存在的时候才插入数据
	RPop - 从列表的右边删除第一个数据，并返回删除的数据
	RPush - 从列表右边插入数据
	RPushX - 跟RPush的区别是，仅当列表存在的时候才插入数据
	LPop - 从列表左边删除第一个数据，并返回删除的数据
	LLen - 返回列表的大小
	LRange - 返回列表的一个范围内的数据，也可以返回全部数据
	LRem - 删除列表中的数据
	LIndex - 根据索引坐标，查询列表中的数据
	LInsert - 在指定位置插入数据
	Ltrim - 对一个列表进行修剪(trim)，就是说，让列表只保留指定区间内的元素，不在指定区间之内的元素都将被删除 LTRIM KEY_NAME START STOP
	Rpoplpush - 命令用于移除列表的最后一个元素，并将该元素添加到另一个列表并返回
	Brpop  - 命令移出并获取列表的最后一个元素， 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
	Blpop  - 命令移出并获取列表的第一个元素， 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
	lpush + rpop / rpush + lpop 实现消息队列，先进先出
	lpush + brpop 实现阻塞式消息队列
	l/rpush + ltrim 实现有限集合
*/

func main() {
	//(0)初始化一个新的redis client
	client := redis.NewClient(&redis.Options{
		Addr:     "localhost:6379", // redis地址
		Password: "",               // redis没密码，没有设置，则留空
		DB:       0,                // 使用默认数据库
	})

	//(1)LPush从列表左边插入数据
	// 插入一个数据
	client.LPush("key", "data1")

	// LPush支持一次插入任意个数据
	err := client.LPush("key", 1, 2, 3, 4, 5).Err()
	if err != nil {
		panic(err)
	}

	//(2)LPushX跟LPush的区别是，仅当列表存在的时候才插入数据,用法完全一样。
	//(3)RPop从列表的右边删除第一个数据，并返回删除的数据
	val, err := client.RPop("key").Result()
	if err != nil {
		panic(err)
	}

	fmt.Println(val)

	//(4)RPush从列表右边插入数据
	// 插入一个数据
	client.RPush("key", "data1")

	// 支持一次插入任意个数据
	errl := client.RPush("key", 1, 2, 3, 4, 5).Err()
	if errl != nil {
		panic(errl)
	}

	//(5)RPushX跟RPush的区别是，仅当列表存在的时候才插入数据, 他们用法一样
	//(6)LPop从列表左边删除第一个数据，并返回删除的数据
	val1, err := client.LPop("key").Result()
	if err != nil {
		panic(err)
	}

	fmt.Println(val1)

	//(8)LLen返回列表的大小
	val2, err := client.LLen("key").Result()
	if err != nil {
		panic(err)
	}

	fmt.Println(val2)

	//(8)LRange返回列表的一个范围内的数据，也可以返回全部数据
	// 返回从0开始到-1位置之间的数据，意思就是返回全部数据
	vals, err := client.LRange("key", 0, -1).Result()
	if err != nil {
		panic(err)
	}
	fmt.Println(vals)

	//(9LRem删除列表中的数据
	// 从列表左边开始，删除100， 如果出现重复元素，仅删除1次，也就是删除第一个
	dels, err := client.LRem("key", 1, 100).Result()
	if err != nil {
		panic(err)
	}
	fmt.Println(dels)
	// 如果存在多个100，则从列表左边开始删除2个100
	client.LRem("key", 2, 100)

	// 如果存在多个100，则从列表右边开始删除2个100
	// 第二个参数负数表示从右边开始删除几个等于100的元素
	client.LRem("key", -2, 100)

	// 如果存在多个100，第二个参数为0，表示删除所有元素等于100的数据
	client.LRem("key", 0, 100)

	//(10)LIndex根据索引坐标，查询列表中的数据
	// 列表索引从0开始计算，这里返回第6个元素
	valk, err := client.LIndex("key", 5).Result()
	if err != nil {
		panic(err)
	}
	fmt.Println(valk)

	//(11)LInsert在指定位置插入数据
	// 在列表中5的前面插入4
	// before是之前的意思
	errk := client.LInsert("key", "before", 5, 4).Err()
	if errk != nil {
		panic(errk)
	}

	// 在列表中 tizi365 元素的前面插入 欢迎你
	client.LInsert("key", "before", "tizi365", "欢迎你")

	// 在列表中 tizi365 元素的后面插入 2019
	client.LInsert("key", "after", "tizi365", "2019")
}
